package cs236369.webserver;

import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.Collection;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.TreeMap;

import org.apache.http.HttpException;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.ProtocolVersion;
import org.apache.http.entity.FileEntity;
import org.apache.http.protocol.HTTP;
import org.apache.http.protocol.HttpContext;
import org.apache.http.protocol.HttpDateGenerator;
import org.apache.http.protocol.HttpRequestHandler;
import cs236369.webserver.DTOs.MimeMapping;

public class DefaultHandler implements HttpRequestHandler {

	private Collection<MimeMapping> mimes = null;
	private final HttpDateGenerator dgen = new HttpDateGenerator();
	
	public DefaultHandler (Properties p) {
		
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public void handle(HttpRequest request, HttpResponse response,
			HttpContext context) throws HttpException, IOException {
		
		Map<String,String> queryParams = new TreeMap<String,String>();
		String path = getPathAndParams(request, queryParams);
		File f = new File((String)context.getAttribute("baseDir"),path);
		
		if(request.getRequestLine().getMethod().toUpperCase(Locale.ENGLISH) == "POST") {
			setError(response,HttpStatus.SC_METHOD_NOT_ALLOWED, "Wrong Method");
			return;
		}
		if (f.isDirectory() || !f.exists()) {
			setError(response,HttpStatus.SC_NOT_FOUND, "Not Exists");
			return;
		}
		this.mimes = (Collection<MimeMapping>) context.getAttribute("mimes");

		FileEntity fen = new FileEntity(f,mimeLookup(f));
		response.setStatusLine(new ProtocolVersion("HTTP",1,1), HttpStatus.SC_OK, "OK");
		response.setHeader(HTTP.CONTENT_LEN, Long.toString(f.length()));
		response.setHeader(HTTP.DATE_HEADER, dgen.getCurrentDate());
		response.setHeader(HTTP.CONN_DIRECTIVE, HTTP.CONN_CLOSE);
		if (fen.getContentType() != null) {
			response.setHeader(fen.getContentType());
		}
		response.setEntity(fen);
	}
	
	private void setError(HttpResponse response, int statusCode, String reason) {
			HttpDateGenerator dgen = new HttpDateGenerator();
			response.setStatusLine(new ProtocolVersion("HTTP", 1, 1), statusCode, reason);
			response.setHeader(HTTP.CONTENT_LEN, "0");
			response.setHeader(HTTP.DATE_HEADER,dgen.getCurrentDate());
			response.setHeader(HTTP.CONN_DIRECTIVE, HTTP.CONN_CLOSE);
	}
	
	private String mimeLookup(File f) throws IOException {
		String res = "";
		synchronized (mimes) {
			for(MimeMapping mm : mimes) {
				if(f.getCanonicalPath().endsWith(mm.getExtension())) {
					res = mm.getMimeType();
					break;
				}
			}
		}
		return res;
	}

	private String getPathAndParams(HttpRequest req, Map<String,String> m) {
		String query = null;
		String path = null;
		try {
			// for parsing's sake, assume it's an absolute URL
			URL url = new URL(req.getRequestLine().getUri());
			query = url.getQuery();
			path = url.getPath();
		} catch(MalformedURLException e) {
			// so it was a relative URL, no biggy
			String[] sp = req.getRequestLine().getUri().split("\\?");
			path = sp[0];
			if(sp.length > 1)
				query = sp[1];
			query = null;
		}
		
		queryIntoMap(query, m);
		return path;
	}

	private void queryIntoMap(String query, Map<String, String> m) {
		if(query != null && m != null)
			for(String param : query.split("&")) {
				String[] p = param.split("=");
				try {
					String key = URLDecoder.decode(p[0], "UTF-8");
					String value = URLDecoder.decode(p[1], "UTF-8");
					m.put(key, value);
				} catch(UnsupportedEncodingException e) {
					//TODO Tough Luck
				}
			}
	}

}
